/**
 * 
 */
package abel.wlmr.server;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import abel.util.HexString;
import abel.wlmr.config.MeterStation;
import abel.wlmr.config.MsaConfig;
import abel.wlmr.config.MsaConfigLoader;
import abel.wlmr.model.WlmrLinkException;
import abel.wlmr.model.WlmrPacket;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

/**
 * @author Abel
 *
 */
public class WlmrPacketDecoder extends ByteToMessageDecoder {
    private Logger log;

    public WlmrPacketDecoder() {
        MsaConfig msaConfig = MsaConfigLoader.getMsaConfig();
        log = LoggerFactory.getLogger(msaConfig.getMain().getA1().getAsc());
    }

    /* (non-Javadoc)
     * @see io.netty.handler.codec.ByteToMessageDecoder#decode(io.netty.channel.ChannelHandlerContext, io.netty.buffer.ByteBuf, java.util.List)
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // get log for current station
        MeterStation station = ctx.channel().attr(PacketConsts.stationKey).get();
        if (station != null) {
            log = LoggerFactory.getLogger(station.getAddr().stationKey());
        }

        log.info("Up bytes: {}", HexString.bytesToHexStringWithBlank(in.duplicate()));

        WlmrPacket p = null;

        do {
            p = new WlmrPacket(log);
            p.tryFindHead(in);

            try {
                int plen = p.parseBuf(in);

                // deal parsing result.
                if (plen > 0) {
                    out.add(p);

                    // log.
                    log.info("UP {} from {} ({}): {}", p.getAfn(), ctx.name(), p.getAddr().stationKey(), p);
                } else {
                    // break if not whole packet.
                    p = null;
                }
            } catch (WlmrLinkException e) {
                log.error("Link may be corruptted caused by " + e.getMessage(), e);
                throw e;
            } catch (Exception e) {
                log.error("Fail to parse bytes caused by {} so just neglecting it...", e.getMessage());

                // if the link seems not correct, so neglect it.
                p = null;
            }
        } while (p != null);

        // log.
        String afn = out.isEmpty() ? "" : ((WlmrPacket) out.get(0)).getAfn().toString();
        log.info("Up {} packets [{}...] and left bytes: {}.",
            out.size(), afn, in.readableBytes());
    }

}
